#coding=utf-8

module Aio::Text
  class Context < ::Array

    class OutLineError < StandardError; end

    include Aio::Ui::Verbose

    attr_reader :count_line, :backup_line

    def initialize(*arr)
      super
      self.each_with_index do |str, i|
        self[i] = Aio::Text::LineString.new(str.chomp)
      end
      @backup_line = nil
      @count_line = 0
    end

    # 到下一行
    def next
      @count_line += 1
    end

    # 对每行进行read, 判断是单步运行还是循环运行
    # 修改了此处的backup_line 逻辑
    def readline_match_block(reg, single = false, &block)

      reg = Aio::Base::Toolkit::Regexp.safe(reg)

      first = true
      loop do 
        line_str = self[@count_line]

        if first
          @backup_line = @count_line
        end

        # 如果出界，有可能是因为循环导致
        # 跳出循环
        # 此处有问题，无法判断是否为最后一个，并跳出此模块
        if @backup_line > self.size and line_str.nil?
          @count_line = @backup_line
          if Aio::Base::Debug.mismatch?
            puts "[-] Can't match this line: "
            puts caller
            puts "  line_string: #{self[@backup_line]}"
            puts "  regexp: #{reg}"
          end
          raise OutLineError
        end

        if line_str.nil?
          @count_line = @backup_line
          break
        end

        first = false
        begin
          res = line_str.match_block(reg, self, @count_line) do |b|
            block.call(b) unless block.nil?
          end
        rescue IndexError => e
          print_error "IndexError: 请检查模块block提取信息名称"
          puts "caller"
          puts caller
          exit
        rescue NoMethodError
          if Aio::Base::Debug.module_debug?
            print_error "NoMethodError: 请检查模块block中useful是否定义正确"
            puts caller
          end
          exit
        rescue ArgumentError => e
          if Aio::Base::Debug.module_debug?
            puts "ArgumentError:"
            puts e.message
            puts caller
          end
        end

        @count_line += 1

        # 如果匹配到，跳出循环
        break if res

        # 如果只是单步运行，就返回
        break if single
      end
    end

    # 单行循环
    # stop 为停止出，在停止处之前的每一行都将输出
    def readline_match_block_loop(start, stop, &block)
      stop = Aio::Base::Toolkit::Regexp.safe(stop)
      loop do 
        readline_match_block(start, true, &block)
        break if stop.match(self[@count_line])
        break if self[@count_line].nil?
      end
    end

    # 读取一个区间，并返回块
    # 只会执行一次
    # stop 作为分裂符
    # opt 当last为false时，不会对stop一行输出
    # opt 当before为true时，只会分裂stop的前一行，count_line保留
    def readline_range(start, stop, opt={:last=>false}, &block)
      str_context = Context.new
      start = Aio::Base::Toolkit::Regexp.safe(start)
      stop = Aio::Base::Toolkit::Regexp.safe(stop)
      backup_line = @count_line

      loop do 
        line_str = self[@count_line]

        if line_str.nil?
          @count_line = backup_line
          raise OutLineError
        end

        if start =~ line_str
          str_context << line_str
          @count_line += 1
          break
        end
        @count_line += 1
      end

      loop do 
        line_str = self[@count_line]
        #raise OutLineError if line_str.nil?
        if stop =~ line_str or line_str.nil?
          str_context << line_str if opt[:last]
          @count_line += 1 unless opt[:before]
          break
        else
          str_context << line_str
        end
        @count_line += 1
      end

      block.call(str_context)
    end

    # 当需要多次循环时使用
    # 此方法用于循环更加安全
    def readline_range_loop(start, stop, opt={:last=>false}, &block)
      loop do 
        begin
          readline_range(start, stop, opt, &block)
        rescue OutLineError
          break
        end
      end
    end

    # 读取一个区间并返回块
    # 在起始位置之后的行中，满足条件, 则放入同一区间。否则返回
    def readline_range_if(start, condition, &block)
      str_context = Context.new
      start = Aio::Base::Toolkit::Regexp.safe(start)
      condition = Aio::Base::Toolkit::Regexp.safe(condition)

      loop do
        line_str = self[@count_line]
        raise OutLineError if line_str.nil?
        if start =~ line_str
          str_context << line_str
          @count_line += 1
          break
        end
        @count_line += 1
      end

      loop do
        line_str = self[@count_line]
        if condition =~ line_str
          str_context << line_str
          @count_line += 1
        else
          break
        end
      end

      block.call(str_context)
    end

    def readline_range_if_loop(start, condition, &block)
      loop do
        begin
          readline_range_if(start, condition, &block)
        rescue OutLineError
          break
        end
      end
    end

    def count_line
      self[@count_line]
    end

    def method_missing(mid, *arg, &block)
      print_error "#{mid} 方法未定义，请检查方法名拼写"
      puts caller[0]
      super
    end

  end
end
